/*
frigOS
Licensed under GPLv3

Prototypes and definitions for using USART0
Included by default in serial.h
*/

#ifndef __USART0_H__
#define __USART0_H__

#include "serial.h"
#include "kernel.h"
#include "dynamixel.h"
#include "defs.h"

// USART0 baud rate is fixed
// uncomment the appropriate section for the desired baud rate
// 1000000 (1M) (standard for MX-28)
#define USART0_BAUD_RATE_HI 0x00
#define USART0_BAUD_RATE_LO 0x01
// 0.5M (standard for AX-12)
//#define USART0_BAUD_RATE_HI 0x00
//#define USART0_BAUD_RATE_LO 0x03

// set Tx or Rx on USART0
static inline void setRxUSART0(void)
{
    PORTE &= ~(1 << PE2);
    PORTE |= (1 << PE3);
}
static inline void setTxUSART0(void)
{
    PORTE &= ~(1 << PE3);
    PORTE |= (1 << PE2);
}

// check TX or RX on USART0
static inline BOOL isRxUSART0(void)
{
    return (!(PORTE & (1 << PE2)) && (PORTE & (1 << PE3)));
}

#define USART0_RX_BUFFER_SIZE 32
#define USART0_TX_BUFFER_SIZE 32

#define USART0_PACKET_HEADER0   0xff
#define USART0_PACKET_HEADER1   0xff

// important indices in the instruction/response packets (including the FF FF header)
#define USART0_PACKET_ID_BYTE            2
#define USART0_PACKET_LENGTH_BYTE        3
#define USART0_PACKET_INSTRUCTION_BYTE   4
#define USART0_PACKET_ERROR_BYTE         4
#define USART0_PACKET_PARAMETER_1_BYTE   5

// what is the current state of the packet being received?
enum USART0_STATE
{
    USART0_INITIAL_STATE,       // waiting for the first byte
    USART0_HEADER1_STATE,       // received the first FF byte
    USART0_HEADER2_STATE,       // received the second FF byte
    USART0_ID_STATE,            // received the ID byte
    USART0_LENGTH_STATE,        // received the length byte
    USART0_ERROR_STATE,         // received the error code byte
    USART0_PARAMETER_STATE,     // received 1+ parameters
    USART0_CHECKSUM_STATE       // received all parameters & checksum
};

// USART0 is controlled by a single lock
// ensure that you have locked the semaphore before sending bytes
extern volatile Semaphore usart0_lock;

// queues used for I/O
// these should not be modified by the user
extern volatile IO_Queue rxQueue_USART0;
extern volatile IO_Queue txQueue_USART0;

// bytes received from the AX-12 motors are stored in a packet struct
extern volatile DXL_Packet responsePacket;

// access to the packet struct is controlled by this lock
extern volatile Semaphore responsePacketLock;

// initialize USART0 for communication with the dynamixel devices
void initUSART0(void);

// fetch a byte from the Rx queue
// 0x00 is returned if the queue is empty
// check rxQueue_USART0.empty before calling this function
uint8_t getByteUSART0(void);

// transmit an array of bytes
void transmitBufferUSART0(uint8_t const buffer[], uint8_t buffer_length);

// transmit an array of bytes bypassing the normal interrupt-driven i/o
// this should ONLY be used for debugging or transmitting messages inside an interrupt
void transmitBufferUSART0_busyLoop(uint8_t const buffer[], uint8_t buffer_length);

// transmit a single byte
void transmitByteUSART0(uint8_t msg);

// transmit a packet
void transmitPacketUSART0(DXL_Packet *packet);

// transmit a single byte, bypassing the normal interrupt-driven i/o
// this should ONLY be used for debugging or transmitting messages inside an interrupt
void transmitByteUSART0_busyLoop(char msg);

// threadable function
// listen for bytes recieved over USART0 and buffer them
// fires STATUS_PACKET_RECIEVED_EVENT whenever a complete packet is received
void monitorUSART0(void* arg);

#endif  // __USART0_H__

